package com.bwstudio.demo.consumer.controller;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;

import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import com.bwstudio.demo.provider.api.OtherService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
public class AsyncController {
	
	@Reference
	OtherService otherService;

	@GetMapping(value = "/block")
    public String block() {
        log.info("----- Request received -----");
        long startTime = System.currentTimeMillis();
        String result = otherService.doFirst();
        long endTime = System.currentTimeMillis() - startTime;
        log.info("一个 同步请求 + 同步调用 共计用时（毫秒）：" + endTime);
        log.info("----- Servlet thread released -----");
        return result;
    }
	
	@GetMapping("/callable")
	public Callable<String> asyncCallable() {
        log.info("----- Request received -----");
        long startTime = System.currentTimeMillis();
		//Callable<String> 的抽象方法签名是 () -> String, 和Lambda表达式 () -> "String" 的签名是一致的, 所以可以将其作为方法返回值。
		// 实例对象引用实例方法, 
		//"lowerCase"::toUpperCase
		//() -> "lowerCase".toUpperCase();
        Callable<String> callable = otherService::doFirst;
        long endTime = System.currentTimeMillis() - startTime;
        log.info("一个 异步请求 + 同步调用 共计用时（毫秒）：" + endTime);
        log.info("----- Servlet thread released -----");
        return callable;
	}
	
	@GetMapping("/deferred")
	public DeferredResult<String> asyncDeferred() {
		log.info("----- Request received -----");
		DeferredResult<String> deferredResult = new DeferredResult<>();
		
		long startTime = System.currentTimeMillis();

		// 异步调用
		CompletableFuture<String> doThirdFuture = otherService.doThird();

		long asyncInvokeuseTime = System.currentTimeMillis() - startTime;
//		log.info("一个异步调用共计用时（毫秒）：" + asyncInvokeuseTime);
		log.info("一个 异步请求 + 异步调用 共计用时（毫秒）：" + asyncInvokeuseTime);
		doThirdFuture.whenComplete((result, throwable) -> {
			if (throwable != null) {
				throwable.printStackTrace();
			} else {
				log.info("异步调用提供者的doThird()返回值：" + result);
				deferredResult.setResult(result);
			}
		});
		
		
		log.info("----- Servlet thread released -----");
		return deferredResult;
	}
}
